package xserver.codec;

import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Map;

import org.json.JSONException;
import org.json.JSONObject;

import xgame.XgameError;
import xgame.XpropertyContainer;

/**
 * JSON 序列化器
 * 
 * @author AfritXia
 *
 */
public class JSONSerializer {
	/**
	 * 序列化属性容器
	 * 
	 * @param container
	 * @return 
	 * 
	 */
	public byte[] serialize(XpropertyContainer container) {
		if (container == null) {
			return null;
		}

		// 获取 JSON 对象
		JSONObject json = (new PropertyContainer2JSON()).getJSONObject(container);

		if (json == null) {
			return null;
		}

		// 获取 JSON 字符串
		String jsonStr = json.toString();

		if (jsonStr == null) {
			return null;
		}

		return jsonStr.getBytes(Charset.forName("UTF-8"));
	}

	/**
	 * 将 PropertyContainer 转换成 JSON
	 * 
	 * @author AfritXia
	 *
	 */
	private class PropertyContainer2JSON extends XpropertyContainer.Friend {
		/**
		 * 获取 JSON 对象
		 * 
		 * @param container
		 * @return 
		 * 
		 */
		private JSONObject getJSONObject(XpropertyContainer container) {
			if (container == null) {
				return null;
			}

			// 获取内置字典
			Map<String, Object> innerMap = this.getInnerMap(container);

			if (innerMap == null || 
				innerMap.size() <= 0) {
				return null;
			}

			// 创建 JSON 对象
			JSONObject json = new JSONObject();
			// 获取关键字迭代器
			Iterator<String> it = innerMap.keySet().iterator();

			try {
				while (it.hasNext()) {
					// 获取关键字
					String key = it.next();
					// 获取字典值
					Object value = innerMap.get(key);

					if (value instanceof XpropertyContainer) {
						// 设置内置容器
						json.put(key, this.getJSONObject((XpropertyContainer)value));
					} else {
						// 设置对象
						json.put(key, value);
					}
				}
			} catch (JSONException ex) {
				throw new XgameError(ex);
			}

			return json;
		}
	}

	/**
	 * 反序列化
	 * 
	 * @param source
	 * @return 
	 * 
	 */
	public XpropertyContainer deserialize(byte[] source) {
		if (source == null) {
			return null;
		}

		// 获取 JSON 字符串
		String jsonStr = new String(source, Charset.forName("UTF-8"));

		try {
			// 创建 JSON 对象
			JSONObject json = new JSONObject(jsonStr);
			// 创建序列化容器
			XpropertyContainer container = (new JSON2PropertyContainer()).getPropertyContainer(json);

			return container;
		} catch (JSONException ex) {
			throw new XgameError(ex);
		}
	}

	/**
	 * 将 PropertyContainer 转换成 JSON
	 * 
	 * @author AfritXia
	 *
	 */
	private class JSON2PropertyContainer extends XpropertyContainer.Friend {
		/**
		 * 获取序列化容器
		 * 
		 * @param fromJson
		 * 
		 */
		private XpropertyContainer getPropertyContainer(JSONObject fromJson) {
			if (fromJson == null) {
				return null;
			}
	
			// 创建序列化容器
			XpropertyContainer container = new XpropertyContainer();
			// 获取内置字典
			Map<String, Object> innerMap = this.getInnerMap(container);

			@SuppressWarnings("unchecked")
			Iterator it = fromJson.keys();

			try {
				while (it.hasNext()) {
					// 获取 JSON 关键字
					String key = (String)it.next();
					// 获取 JSON 值
					Object obj = fromJson.get(key);
					
					if (obj instanceof JSONObject) {
						// 设置子容器
						innerMap.put(key, this.getPropertyContainer((JSONObject)obj));
					} else {
						// 设置键值对
						innerMap.put(key, obj);
					}
				}
			} catch (JSONException ex) {
				throw new XgameError(ex);
			}
	
			return container;
		}
	}
}
